using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace FolderSizeAnalyzer
{
    public partial class MainForm : Form
    {
        private BackgroundWorker worker;
        private bool analyzeFiles = false;
        private bool isPaused = false;

        private ContextMenuStrip listViewContextMenu;
        
        public MainForm()
        {
            InitializeComponent();
            
            // 初始化右键菜单
            listViewContextMenu = new ContextMenuStrip();
            var deleteMenuItem = new ToolStripMenuItem("删除");
            deleteMenuItem.Click += DeleteMenuItem_Click;
            listViewContextMenu.Items.Add(deleteMenuItem);
            lvItems.ContextMenuStrip = listViewContextMenu;
            
            // 初始化BackgroundWorker
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.DoWork += Worker_DoWork;
            worker.ProgressChanged += Worker_ProgressChanged;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (analyzeFiles)
            {
                using (var openFileDialog = new OpenFileDialog())
                {
                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        txtFolderPath.Text = openFileDialog.FileName;
                    }
                }
            }
            else
            {
                using (var folderDialog = new FolderBrowserDialog())
                {
                    if (folderDialog.ShowDialog() == DialogResult.OK)
                    {
                        txtFolderPath.Text = folderDialog.SelectedPath;
                    }
                }
            }
        }

        private long totalItems = 0;
        private long processedItems = 0;
        
        private void btnAnalyze_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtFolderPath.Text))
            {
                MessageBox.Show("请先选择路径");
                return;
            }

            if (worker.IsBusy)
            {
                worker.CancelAsync();
                btnAnalyze.Text = "开始分析";
                btnPause.Enabled = false;
                return;
            }

            lvItems.Items.Clear();
            progressBar1.Value = 0;
            totalItems = 0;
            processedItems = 0;
            isPaused = false;

            btnAnalyze.Text = "停止分析";
            btnPause.Enabled = true;
            btnPause.Text = "暂停分析";
            radioButtonFiles.Enabled = false;
            radioButtonFolders.Enabled = false;

            worker.RunWorkerAsync(txtFolderPath.Text);
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            if (isPaused)
            {
                isPaused = false;
                btnPause.Text = "暂停分析";
                worker.RunWorkerAsync(txtFolderPath.Text);
            }
            else
            {
                isPaused = true;
                worker.CancelAsync();
                btnPause.Text = "继续分析";
                radioButtonFiles.Enabled = false;
                radioButtonFolders.Enabled = false;
            }
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            string path = (string)e.Argument;
            var items = new List<FileSystemItem>();
            
            if (analyzeFiles)
            {
                var fileInfo = new FileInfo(path);
                items.Add(new FileSystemItem
                {
                    Name = fileInfo.Name,
                    Path = fileInfo.FullName,
                    Size = fileInfo.Length,
                    IsDirectory = false
                });
            }
            else
            {
                ScanFolder(path, items, (BackgroundWorker)sender);
            }

            e.Result = items;
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState != null)
            {
                lblStatus.Text = e.UserState.ToString();
            }
            
            if (totalItems > 0)
            {
                int progress = (int)((double)processedItems / totalItems * 100);
                progressBar1.Value = progress;
                lblStatus.Text = $"正在分析... {progress}% 完成 ({processedItems}/{totalItems} 项)";
            }
            else
            {
                progressBar1.Value = e.ProgressPercentage;
            }
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show($"分析出错: {e.Error.Message}");
            }
            else if (!e.Cancelled || isPaused)
            {
                if (!isPaused)
                {
                    var items = (List<FileSystemItem>)e.Result;
                    var sortedItems = items.OrderByDescending(i => i.Size).ToList();
                    
                    foreach (var item in sortedItems)
                    {
                        var listItem = new ListViewItem(item.Name);
                        listItem.SubItems.Add(FormatSize(item.Size));
                        listItem.SubItems.Add(item.IsDirectory ? "Folder" : "File");
                        listItem.Tag = item.Path;
                        
                        if (item.Size > 524288000) // 500MB = 524288000 bytes
                        {
                            listItem.ForeColor = Color.Red;
                            foreach (ListViewItem.ListViewSubItem subItem in listItem.SubItems)
                            {
                                subItem.ForeColor = Color.Red;
                            }
                        }
                        
                        lvItems.Items.Add(listItem);
                    }
                }

                if (!isPaused)
                {
                    btnAnalyze.Text = "开始分析";
                    btnPause.Enabled = false;
                    progressBar1.Value = 100;
                    radioButtonFiles.Enabled = true;
                    radioButtonFolders.Enabled = true;
                }
            }
        }

        private void radioButtonFiles_CheckedChanged(object sender, EventArgs e)
        {
            analyzeFiles = radioButtonFiles.Checked;
        }

        private void ScanFolder(string folderPath, List<FileSystemItem> items, BackgroundWorker worker)
        {
            try
            {
                // 预计算总项目数
                if (totalItems == 0)
                {
                    totalItems = Directory.GetFiles(folderPath).Length + Directory.GetDirectories(folderPath).Length;
                }

                // Add files in current directory
                var files = Directory.GetFiles(folderPath);
                for (int i = 0; i < files.Length; i++)
                {
                    var file = files[i];
                    var fileInfo = new FileInfo(file);
                    items.Add(new FileSystemItem
                    {
                        Name = fileInfo.Name,
                        Path = fileInfo.FullName,
                        Size = fileInfo.Length,
                        IsDirectory = false
                    });

                    processedItems++;
                    worker.ReportProgress((i * 100) / files.Length, $"正在分析: {fileInfo.Name}");
                }
                
                // Add subdirectories
                var dirs = Directory.GetDirectories(folderPath);
                for (int i = 0; i < dirs.Length; i++)
                {
                    var dir = dirs[i];
                    var dirInfo = new DirectoryInfo(dir);
                    long size = CalculateDirectorySize(dir, worker);
                    items.Add(new FileSystemItem
                    {
                        Name = dirInfo.Name,
                        Path = dirInfo.FullName,
                        Size = size,
                        IsDirectory = true
                    });

                    processedItems++;
                    worker.ReportProgress((i * 100) / dirs.Length, $"正在分析: {dirInfo.Name}");
                }
            }
            catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
            {
                // Skip files/folders we can't access or have issues with
                worker.ReportProgress(0, $"跳过: {folderPath} - {ex.Message}");
            }
        }

        private long CalculateDirectorySize(string directoryPath, BackgroundWorker worker)
        {
            long size = 0;
            DateTime lastUpdate = DateTime.MinValue;
            
            try
            {
                // Add file sizes
                var files = Directory.GetFiles(directoryPath);
                for (int i = 0; i < files.Length; i++)
                {
                    if (worker.CancellationPending) return 0;
                    
                    size += new FileInfo(files[i]).Length;
                    
                    // 限制UI更新频率
                    if ((DateTime.Now - lastUpdate).TotalMilliseconds > 100 || i == files.Length - 1)
                    {
                        worker.ReportProgress((i * 100) / files.Length, $"计算大小: {Path.GetFileName(files[i])}");
                        lastUpdate = DateTime.Now;
                    }
                }
                
                // Add subdirectory sizes
                var dirs = Directory.GetDirectories(directoryPath);
                for (int i = 0; i < dirs.Length; i++)
                {
                    if (worker.CancellationPending) return 0;
                    
                    size += CalculateDirectorySize(dirs[i], worker);
                    
                    // 限制UI更新频率
                    if ((DateTime.Now - lastUpdate).TotalMilliseconds > 100 || i == dirs.Length - 1)
                    {
                        worker.ReportProgress((i * 100) / dirs.Length, $"计算子目录: {Path.GetFileName(dirs[i])}");
                        lastUpdate = DateTime.Now;
                    }
                }
            }
            catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
            {
                // Skip directories we can't access or have issues with
                worker.ReportProgress(0, $"跳过: {directoryPath} - {ex.Message}");
                return 0;
            }
            
            return size;
        }

        private string FormatSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private void lvItems_DoubleClick(object sender, EventArgs e)
        {
            if (lvItems.SelectedItems.Count == 0) return;
            
            var path = lvItems.SelectedItems[0].Tag as string;
            if (Directory.Exists(path))
            {
                // 打开文件夹
                System.Diagnostics.Process.Start("explorer.exe", path);
            }
            else if (File.Exists(path))
            {
                // 打开文件所在文件夹并选中文件
                System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
            }
        }
        
        private BackgroundWorker deleteWorker;
        private bool isDeleting = false;
        
        private void DeleteMenuItem_Click(object sender, EventArgs e)
        {
            if (lvItems.SelectedItems.Count == 0 || isDeleting) return;
            
            var path = lvItems.SelectedItems[0].Tag as string;
            if (path == null) return;
            
            // 检查是否是系统关键文件/文件夹
            if (IsSystemCritical(path))
            {
                MessageBox.Show("无法删除系统关键文件/文件夹", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            // 确认删除对话框
            var confirmResult = MessageBox.Show($"确定要删除 '{Path.GetFileName(path)}' 吗?", 
                "确认删除", 
                MessageBoxButtons.YesNo, 
                MessageBoxIcon.Warning);
                
            if (confirmResult == DialogResult.Yes)
            {
                isDeleting = true;
                btnAnalyze.Enabled = false;
                btnPause.Enabled = false;
                lblStatus.Text = "正在删除...";
                
                deleteWorker = new BackgroundWorker();
                deleteWorker.WorkerReportsProgress = true;
                deleteWorker.WorkerSupportsCancellation = true;
                deleteWorker.DoWork += (s, args) => {
                    try
                    {
                        if (Directory.Exists(path))
                        {
                            DeleteDirectory(path, deleteWorker);
                        }
                        else if (File.Exists(path))
                        {
                            File.Delete(path);
                        }
                        args.Result = true;
                    }
                    catch (Exception ex)
                    {
                        args.Result = ex;
                    }
                };
                deleteWorker.RunWorkerCompleted += (s, args) => {
                    isDeleting = false;
                    btnAnalyze.Enabled = true;
                    btnPause.Enabled = true;
                    
                    if (args.Result is Exception ex)
                    {
                        MessageBox.Show($"删除失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        lvItems.Items.Remove(lvItems.SelectedItems[0]);
                        lblStatus.Text = "删除完成";
                    }
                };
                
                deleteWorker.RunWorkerAsync();
            }
        }
        
        private void DeleteDirectory(string targetDir, BackgroundWorker worker)
        {
            string[] files = Directory.GetFiles(targetDir);
            string[] dirs = Directory.GetDirectories(targetDir);

            foreach (string file in files)
            {
                if (worker.CancellationPending) return;
                
                File.SetAttributes(file, FileAttributes.Normal);
                File.Delete(file);
                worker.ReportProgress(0, $"正在删除文件: {Path.GetFileName(file)}");
            }

            foreach (string dir in dirs)
            {
                if (worker.CancellationPending) return;
                DeleteDirectory(dir, worker);
            }

            Directory.Delete(targetDir, false);
        }
        
        private bool IsSystemCritical(string path)
        {
            try
            {
                // 检查Windows目录
                if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Windows), StringComparison.OrdinalIgnoreCase))
                    return true;
                    
                // 检查Program Files目录
                if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), StringComparison.OrdinalIgnoreCase) ||
                    path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), StringComparison.OrdinalIgnoreCase))
                    return true;
                    
                // 检查系统注册表项
                if (Path.GetExtension(path).Equals(".dll", StringComparison.OrdinalIgnoreCase) ||
                    Path.GetExtension(path).Equals(".exe", StringComparison.OrdinalIgnoreCase) ||
                    Path.GetExtension(path).Equals(".sys", StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }
            catch
            {
                // 如果检查出错，保守起见认为可能是系统文件
                return true;
            }
            
            return false;
        }
    }

    public class FileSystemItem
    {
        public string? Name { get; set; }
        public string? Path { get; set; }
        public long Size { get; set; }
        public bool IsDirectory { get; set; }
    }
}